Skip to content

Fix phpstan/phpstan#5865: Do-while loop broken by exception not supported#5469

Closed
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-8u02zvo
Closed

Fix phpstan/phpstan#5865: Do-while loop broken by exception not supported#5469
phpstan-bot wants to merge 1 commit intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-8u02zvo

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

Fixes phpstan/phpstan#5865

Summary

When a void-typed method or function always throws an exception (but doesn't declare never as its return type), PHPStan was unable to detect that calls to it would always terminate execution. This caused false positive "loop condition is always true" errors for do-while and while loops whose bodies called such methods.

For example:

public function alwaysThrows(): void
{
    throw new \Exception();
}

public function test(): void
{
    do {
        $this->alwaysThrows();
    } while (true); // false positive: "Do-while loop condition is always true."
}

Approach

During method and function body analysis, NodeScopeResolver already tracks execution ends and whether the body always terminates (this is used by NeverRuleHelper to suggest the never return type). This PR stores that "always terminates" information in a lookup map (alwaysTerminatingCallables) keyed by the fully-qualified callable name, then consults it in findEarlyTerminatingExpr when processing:

  • Instance method calls ($this->alwaysThrows())
  • Static method calls (self::staticAlwaysThrows())
  • Function calls (alwaysThrowsFunction())

First-class callable syntax (e.g. $this->method(...)) is explicitly excluded since it creates a closure rather than invoking the method.

Limitation: This only works when the called method/function is analyzed before the caller (same file, declaration order). Cross-file calls won't benefit from this detection — those cases would require declaring never as the return type.

Test plan

  • Added tests/PHPStan/Rules/Comparison/data/bug-5865.php — do-while loop regression tests covering instance methods, variable conditions, never return type, static methods, and function calls
  • Added tests/PHPStan/Rules/Comparison/data/bug-5865-while.php — analogous while loop regression tests
  • Added test methods in DoWhileLoopConstantConditionRuleTest and WhileLoopAlwaysTrueConditionRuleTest
  • All 11857 existing tests continue to pass
  • PHPStan self-analysis passes with no errors

…rted

Detect void methods/functions that always terminate (throw/exit) during
body analysis and suppress false "always true/false" loop condition
reports when such calls appear in loop bodies.
@staabm staabm deleted the create-pull-request/patch-8u02zvo branch April 17, 2026 16:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants